package com.android.lovely.ui.dialog

import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.lifecycleScope
import com.android.lovely.R
import com.android.lovely.api.service.userService
import com.android.lovely.data.getInviteInfo
import com.android.lovely.databinding.DialogInviteCodeBinding
import com.android.lovely.framework.BaseDialogFragment
import com.android.lovely.framework.launchWithLoading
import com.android.lovely.user.UserManager
import com.kotlin.extensions.coroutine.CoroutineExt.launchSafety
import com.kotlin.extensions.keyboard.showKeyboard
import com.kotlin.extensions.view.ViewExt.clickable
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive

class CodeDialog : BaseDialogFragment<DialogInviteCodeBinding>() {

    private val code by lazy { arguments?.getString("code").orEmpty() }

    var onInputCode: (() -> Unit)? = null

    override fun initializeViews() {
        binding.close.clickable { dismiss() }
        binding.confirm.clickable { if (code.isNotEmpty()) dismiss() else bindCode() }
        binding.inputText.isEnabled = code.isEmpty()
        binding.inputLine.isVisible = code.isEmpty()
        binding.c1.isEnabled = code.isEmpty()
        binding.c2.isEnabled = code.isEmpty()
        binding.c3.isEnabled = code.isEmpty()
        binding.c4.isEnabled = code.isEmpty()
        binding.c5.isEnabled = code.isEmpty()
        binding.c6.isEnabled = code.isEmpty()
        binding.c7.isEnabled = code.isEmpty()
        binding.c8.isEnabled = code.isEmpty()
        binding.inputText.doAfterTextChanged {
            val codeText = it?.toString().orEmpty().toMutableList()
            val size = codeText.size
            fillText(codeText)
            binding.confirm.isEnabled = size == 8
            lineCheck(size)
        }
        if (code.isNotEmpty()) {
            binding.inputText.setText(code)
        }
        if (binding.inputText.isEnabled) {
            binding.inputText.post {
                binding.inputText.showKeyboard()
            }
        }
        if (code.isEmpty()) {
            viewLifecycleScope.launchSafety {
                var num = 0
                while (isActive) {
                    binding.inputLine.alpha = if (num % 2 == 0) 1f else 0f
                    delay(500)
                    num++
                }
            }
        }
    }

    private fun lineCheck(size: Int) {
        binding.inputLine.isVisible = code.isEmpty() && size < 8
        binding.inputLine.updateLayoutParams<ConstraintLayout.LayoutParams> {
            startToStart = when (size) {
                1 -> R.id.c2
                2 -> R.id.c3
                3 -> R.id.c4
                4 -> R.id.c5
                5 -> R.id.c6
                6 -> R.id.c7
                7 -> R.id.c8
                else -> R.id.c1
            }
        }
    }

    private fun fillText(codeText: MutableList<Char>) {
        binding.c1.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c2.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c3.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c4.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c5.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c6.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c7.text = codeText.removeFirstOrNull()?.toString().orEmpty()
        binding.c8.text = codeText.removeFirstOrNull()?.toString().orEmpty()
    }

    private fun bindCode() {
        val codeText = binding.inputText.text.toString().trim()
        if (codeText.length != 8) return
        viewLifecycleScope.launchWithLoading {
            val point = userService.writeInviteCode(mapOf("code" to codeText)).getOrDefault("surplus", UserManager.userInfo?.point ?: 0)
            UserManager.updateGems(point)
            getInviteInfo()
            onInputCode?.invoke()
            dismissAllowingStateLoss()
        }
    }
}